﻿// -----------------------------------------------------------------------
// <copyright file="BasecampTests.cs" company="Microsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace DotNet37Signals.Client.Test.Bootstrappers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Configuration;
    using DotNet37Signals.Client.Basecamp;
    using DotNet37Signals.Client.Basecamp.Contracts;
    using DotNet37Signals.Client.Basecamp.Models;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class BasecampTests
    {
        public void Run()
        {
            Console.WriteLine("----------------");
            Console.WriteLine(" Basecamp Tests ");
            Console.WriteLine("----------------");

            this.Initialize();

            this.Account();
            this.Projects();
            this.People();
            this.Companies();
            this.Categories();
            this.Messages();
            this.Comments();
            this.TodoLists();
            this.TodoListItems();
            this.CalendarEntries();
            //this.TimeTracking();
            this.Files();

            Console.WriteLine("");
        }

        public BasecampClient Client { get; set; }

        public void Initialize()
        {
            var username = ConfigurationManager.AppSettings["username.basecamp"];
            var password = ConfigurationManager.AppSettings["password"];
            var company = ConfigurationManager.AppSettings["company"];
            var keepAliveEnabled = Convert.ToBoolean(ConfigurationManager.AppSettings["keepAliveEnabled"]);

            var credentials = new Credentials(username, password, company, keepAliveEnabled);
            this.Client = new BasecampClient(credentials);
        }

        public void Account()
        {
            Console.WriteLine();
            Console.WriteLine("Account Contract Tests");
            Console.WriteLine("**********************");

            var service = this.Client.Account;

            var account = service.Get();

            Console.WriteLine("Account Name: {0}", account.Name);
        }

        public void Projects()
        {
            Console.WriteLine();
            Console.WriteLine("Projects Contract Tests");
            Console.WriteLine("***********************");

            var service = this.Client.Projects;

            var count = service.Count();

            Console.WriteLine("Project Count: Active={0}, Archived={1}, OnHold={2}"
                , count.Active, count.Archived, count.OnHold);

            if (count.Active + count.Archived + count.OnHold > 0)
            {
                var list = service.GetList();

                Console.WriteLine("Project Count: {0}", list.Count);

                var first = list.First();

                var project = service.Get(first.Id);

                Console.WriteLine("Project Name: {0}", project.Name);
            }
        }

        public void People()
        {
            Console.WriteLine();
            Console.WriteLine("People Contract Tests");
            Console.WriteLine("*********************");

            var projectService = this.Client.Projects;
            var companyService = this.Client.Companies;

            var project = projectService.GetList().FirstOrDefault();

            if (project == null)
            {
                Console.WriteLine("No projects exists under this account");
                return;
            }

            Console.WriteLine("Project Name: {0}", project.Name);

            var service = this.Client.People;

            var me = service.Me();

            Console.WriteLine("Me Name: {0} {1}", me.FirstName, me.LastName);

            var people = service.GetList();

            Console.WriteLine("People Count: {0}", people.Count());

            var people2 = service.GetListInProject(project.Id);

            Console.WriteLine("People Count: {0}", people2.Count());

            var company = companyService.GetList().First();
            var people3 = service.GetListInCompany(company.Id);

            Console.WriteLine("People Count: {0}", people3.Count());

            var person = people3.First();

            person = service.Get(person.Id);

            Console.WriteLine("Get Person's Name: {0} {1}", person.FirstName, person.LastName);
        }

        public void Companies()
        {
            Console.WriteLine();
            Console.WriteLine("Companies Contract Tests");
            Console.WriteLine("************************");

            var projectService = this.Client.Projects;

            var project = projectService.GetList().FirstOrDefault();

            if (project == null)
            {
                Console.WriteLine("No projects exists under this account");
                return;
            }

            Console.WriteLine("Project Name: {0}", project.Name);

            var service = this.Client.Companies;

            var companies = service.GetList();

            Console.WriteLine("Companies Count: {0}", companies.Count());

            var companies2 = service.GetListInProject(project.Id);

            Console.WriteLine("Companies Count: {0}", companies2.Count());

            var first = companies.First();

            var company = service.Get(first.Id);

            Console.WriteLine("Get Company Name: {0}", company.Name);
        }

        public void Categories()
        {
            Console.WriteLine();
            Console.WriteLine("Categories Contract Tests");
            Console.WriteLine("*************************");

            var projectService = this.Client.Projects;

            var project = projectService.GetList().FirstOrDefault();

            if (project == null)
            {
                Console.WriteLine("No projects exists under this account");
                return;
            }

            Console.WriteLine("Project Name: {0}", project.Name);

            var service = this.Client.Categories;

            var categories = service.GetList(project.Id);

            Console.WriteLine("Categories Count: {0}", categories.Count());

            var categories2 = service.GetListByType(project.Id, CategoryType.Attachment);

            Console.WriteLine("Attachment Categories Count: {0}", categories2.Count());

            var categories3 = service.GetListByType(project.Id, CategoryType.Post);

            Console.WriteLine("Post Categories Count: {0}", categories3.Count());

            var category = categories.First();

            category = service.Get(category.Id);

            Console.WriteLine("Category: {0}", category.Name);

            var id = service.Create(project.Id, new CategoryNew { Name = "test99", Type = CategoryType.Post });
            var newCategory = service.Get(id.Id);

            Console.WriteLine("New Category: {0}", newCategory.Name);

            service.Update(id.Id, new CategoryUpdate { Name = "test100" });
            var updateCategory = service.Get(id.Id);

            Console.WriteLine("Update Category: {0}", updateCategory.Name);

            service.Delete(id.Id);

            Console.WriteLine("Category Deleted");
        }

        public void Messages()
        {
            Console.WriteLine();
            Console.WriteLine("Messages Contract Tests");
            Console.WriteLine("***********************");

            var projectService = this.Client.Projects;
            var categoryService = this.Client.Categories;

            var project = projectService.GetList().FirstOrDefault();

            if (project == null)
            {
                Console.WriteLine("No projects exists under this account");
                return;
            }

            Console.WriteLine("Project Name: {0}", project.Name);

            var category = categoryService.GetListByType(project.Id, CategoryType.Post).FirstOrDefault();

            var service = this.Client.Messages;

            var messages = service.GetList(project.Id);

            Console.WriteLine("Messages Count: {0}", messages.Count());

            var messages2 = service.GetListByCategory(project.Id, category.Id);

            Console.WriteLine("Messages By Category Name: {1}; Count: {0}", messages2.Count(), category.Name);

            var messages3 = service.GetArchivedList(project.Id);

            Console.WriteLine("Archived Messages Count: {0}", messages3.Count());

            var messages4 = service.GetArchivedListByCategory(project.Id, category.Id);

            Console.WriteLine("Archived Messages By Category Name: {1}; Count: {0}", messages4.Count(), category.Name);
            
            var message = messages.First();

            message = service.Get(message.Id);

            Console.WriteLine("Message: {0}", message.Title);

            var request = new PostNewRequest { Post = new PostNew { Title = "Test", Body = "Testing Body", CategoryId = category.Id, NotifyAboutChanges = false } };
            var id = service.Create(project.Id, request);
            var newPost = service.Get(id.Id);

            Console.WriteLine("New Message: {0}", newPost.Title);

            request.Post.Title = "Test2";
            service.Update(id.Id, request);
            var updateMessage = service.Get(id.Id);

            Console.WriteLine("Update Message: {0}", updateMessage.Title);

            service.Delete(id.Id);

            Console.WriteLine("Message Deleted");
        }

        public void Comments()
        {
            Console.WriteLine();
            Console.WriteLine("Comments Contract Tests");
            Console.WriteLine("***********************");

            var projectService = this.Client.Projects;
            var categoryService = this.Client.Categories;
            var messageService = this.Client.Messages;

            var project = projectService.GetList().FirstOrDefault();

            if (project == null)
            {
                Console.WriteLine("No projects exists under this account");
                return;
            }

            Console.WriteLine("Project Name: {0}", project.Name);

            var category = categoryService.GetListByType(project.Id, CategoryType.Post).FirstOrDefault();
            var message = messageService.GetList(project.Id).FirstOrDefault();

            var service = this.Client.Comments;

            var comments = service.GetList(Resource.Posts, message.Id);

            Console.WriteLine("Comments Count: {0}", comments.Count());

            var newComment = service.New(Resource.Posts, message.Id);

            var request = new CommentNew{ Body = "Hello World" };
            var id = service.Create(Resource.Posts, message.Id, request);
            var newComment2 = service.Get(id.Id);

            Console.WriteLine("New Comment: {0}", newComment2.Body);

            var updateRequest = new CommentNewRequest { Comment = new CommentNew { Body = "changed request" } };
            service.Update(id.Id, updateRequest);
            var updateComment = service.Get(id.Id);

            Console.WriteLine("Update Comment: {0}", updateComment.Body);

            service.Delete(id.Id);

            Console.WriteLine("Comment Deleted");
        }

        public void TodoLists()
        {
            Console.WriteLine();
            Console.WriteLine("TodoLists Contract Tests");
            Console.WriteLine("************************");

            var projectService = this.Client.Projects;
            var companyService = this.Client.Companies;
            var peopleService = this.Client.People;

            var project = projectService.GetList().FirstOrDefault();

            if (project == null)
            {
                Console.WriteLine("No projects exists under this account");
                return;
            }

            Console.WriteLine("Project Name: {0}", project.Name);

            var service = this.Client.TodoLists;

            var todoLists = service.GetList();

            Console.WriteLine("Todo Lists Count: {0}", todoLists.Count());

            var todoLists2 = service.GetListInProject(project.Id, TodoListFilter.All);

            Console.WriteLine("Todo Lists In Project: {1}; Count: {0}", todoLists2.Count(), project.Name);

            var me = peopleService.Me();
            var todoLists3 = service.GetListByResponsiblePerson(me.Id);

            Console.WriteLine("Todo Lists By Me: {1}; Count: {0}", todoLists3.Count(), me.FirstName);

            var company = companyService.GetListInProject(project.Id).FirstOrDefault();
            var todoLists4 = service.GetListByResponsibleCompany(company.Id);

            Console.WriteLine("Todo Lists By Company: {1}; Count: {0}", todoLists4.Count(), company.Name);

            var list = new TodoListNew { Description = "Testing", Name = "Test 123", Private = true, Tracked = false };
            var id = service.Create(project.Id, list);
            var newTodoList = service.Get(id.Id);

            Console.WriteLine("New List: {0}", newTodoList.Name);

            list.Name = "Test 2";
            service.Update(id.Id, list);
            var updateTodoList = service.Get(id.Id);

            Console.WriteLine("Update List: {0}", updateTodoList.Name);

            service.Delete(id.Id);

            Console.WriteLine("List Deleted");        
        }

        public void TodoListItems()
        {
            Console.WriteLine();
            Console.WriteLine("TodoListItems Contract Tests");
            Console.WriteLine("****************************");

            var projectService = this.Client.Projects;
            var todoListService = this.Client.TodoLists;

            var project = projectService.GetList().FirstOrDefault();

            if (project == null)
            {
                Console.WriteLine("No projects exists under this account");
                return;
            }

            Console.WriteLine("Project Name: {0}", project.Name);

            var todoList = todoListService.GetListInProject(project.Id, TodoListFilter.All).FirstOrDefault();

            var service = this.Client.TodoListItems;

            var todoListItems = service.GetList(todoList.Id);

            Console.WriteLine("Todo List Items Count: {0}", todoListItems.Count());

            var todoListItem = service.Get(todoListItems.First().Id);

            Console.WriteLine("Todo List Item: {0}", todoListItem.Content);
            
            var item = new TodoItemNew { Content = "test content", Notify = false, DueAt = DateTime.Now };
            var id = service.Create(todoList.Id, item);
            var newTodoListItem = service.Get(id.Id);

            Console.WriteLine("New Item: {0}", newTodoListItem.Content);

            item.Content = "test content again";
            service.Update(id.Id, item);
            var updateTodoListItem = service.Get(id.Id);

            Console.WriteLine("Update Item: {0}", updateTodoListItem.Content);

            service.Complete(id.Id);

            Console.WriteLine("Item Complete");

            service.Uncomplete(id.Id);

            Console.WriteLine("Item Uncomplete");

            service.Delete(id.Id);

            Console.WriteLine("Item Deleted");
        }

        public void CalendarEntries()
        {
            Console.WriteLine();
            Console.WriteLine("Calendar Entries Contract Tests");
            Console.WriteLine("*******************************");

            var projectService = this.Client.Projects;
            var peopleService = this.Client.People;
            
            var project = projectService.GetList().FirstOrDefault();

            if (project == null)
            {
                Console.WriteLine("No projects exists under this account");
                return;
            }

            Console.WriteLine("Project Name: {0}", project.Name);

            var service = this.Client.CalendarEntries;

            var entries = service.GetList(project.Id);

            Console.WriteLine("Calendar Entries Count: {0}", entries.Count());

            var entries2 = service.GetListEvents(project.Id);

            Console.WriteLine("Calendar Events Count: {0}", entries2.Count());

            var entries3 = service.GetListMilestones(project.Id, CalendarEntryFilter.All);

            Console.WriteLine("Calendar Milestones Count: {0}", entries3.Count());

            var me = peopleService.Me();

            var item = new CalendarEntryRequest { CalendarEntry = new CalendarEntryNew { Title = "Test", Type = CalendarEntryType.Milestone, Deadline = DateTime.Now, ResponsiblePerson = me.Id } };
            var id = service.Create(project.Id, item);
            var newEntry = service.Get(project.Id, id.Id);

            Console.WriteLine("New Entry: {0}", newEntry.Title);

            item.CalendarEntry.Title = "test content again";
            service.Update(project.Id, id.Id, item);
            var updateEntry = service.Get(project.Id, id.Id);

            Console.WriteLine("Update Entry: {0}", updateEntry.Title);

            service.Complete(project.Id, id.Id);

            Console.WriteLine("Entry Complete");

            service.Uncomplete(project.Id, id.Id);

            Console.WriteLine("Entry Uncomplete");

            service.Delete(project.Id, id.Id);

            Console.WriteLine("Entry Deleted");
        }

        public void TimeTracking()
        {
            Console.WriteLine();
            Console.WriteLine("Time Tracking Contract Tests");
            Console.WriteLine("****************************");

            var projectService = this.Client.Projects;
            var peopleService = this.Client.People;

            var project = projectService.GetList().FirstOrDefault();

            if (project == null)
            {
                Console.WriteLine("No projects exists under this account");
                return;
            }

            Console.WriteLine("Project Name: {0}", project.Name);

            var service = this.Client.TimeTracking;

            var entries = service.GetList(project.Id);

            Console.WriteLine("Time Tracking Count: {0}", entries.Count());

            var me = peopleService.Me();
            var item = new TimeEntryNew { Date = DateTime.Now, Description = "testing", Hours = 8, PersonId = me.Id };
            var id = service.Create(project.Id, item);
            var newEntry = service.Get(id.Id);

            Console.WriteLine("New Entry: {0}", newEntry.Description);

            item.Description = "testing again";
            service.Update(id.Id, item);
            var updateEntry = service.Get(id.Id);

            Console.WriteLine("Update Entry: {0}", updateEntry.Description);

            service.Delete(id.Id);

            Console.WriteLine("Entry Deleted");

            var from = new DateTime(2011, 07, 01);
            var to = new DateTime(2011, 12, 31);
            var results = service.Report(c => c.From == from && c.To == to);

            Console.WriteLine("Entry Count: {0}", results.Count());
        }

        public void Files()
        {
            Console.WriteLine();
            Console.WriteLine("Files Contract Tests");
            Console.WriteLine("********************");

            var projectService = this.Client.Projects;

            var project = projectService.GetList().FirstOrDefault();

            if (project == null)
            {
                Console.WriteLine("No projects exists under this account");
                return;
            }

            Console.WriteLine("Project Name: {0}", project.Name);

            var service = this.Client.Files;

            var attachments = service.GetList(project.Id);

            Console.WriteLine("Attachment Count: {0}", attachments.Count);

            foreach (var attachment in attachments)
                Console.WriteLine("Attachment Name: {0}", attachment.Name);
        }
    }
}
